package threadcoreknowledge.threadobjectclasscommonmethods;

/**
 * 描述：     展示wait和notify的基本用法 1. 研究代码执行顺序 2. 证明wait释放锁
 *
 *  * 注意 notify方法,必须在持有锁对象的时候调用,当在synchronized代码块之外调用,会报错
 *  * 持有锁对象的线程,在调用notify方法后,并不会立即释放掉锁,而是走出代码块才会释放锁对象
 *
 *
 */
public class Wait {

    public static Object object = new Object();

    static class Thread1 extends Thread {

        @Override
        public void run() {
            synchronized (object) {
                System.out.println(Thread.currentThread().getName() + "开始执行了-----");
                try {
                    object.wait(); //synchronized获取到哪把锁,就调用哪把锁的notify方法.例如,这里用this.wait()就会报错
                    //被wait的方法,必须在其它线程通过通过锁对象调用notify方法才会唤醒.不然会一直waiting下去
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程" + Thread.currentThread().getName() + "获取到了锁.执行结束了.");
            }

        }
    }

    static class Thread2 extends Thread {

        @Override
        public void run() {
            synchronized (object) {
                System.out.println("线程" + Thread.currentThread().getName() + "执行了,马上调用调用了notify()");
                object.notify();//如果这里不显示调用notify,则线程1会一直处在等待的过程中,
                try {
                    Thread.sleep(1000*3);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

                System.out.println("线程" + Thread.currentThread().getName() + "马上跳出synchronized代码块");
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread1 thread1 = new Thread1();
        Thread2 thread2 = new Thread2();
        thread1.start();
        Thread.sleep(200);
        thread2.start();
    }
}
